home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / netinet / tcp_subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  13.1 KB  |  469 lines

  1. RCS_ID_C="$Id: tcp_subr.c,v 1.7 1993/06/04 11:16:15 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: tcp_subr.c,v $
  9.  * Revision 1.7  1993/06/04  11:16:15  jraja
  10.  * Fixes for first public release.
  11.  *
  12.  * Revision 1.6  1993/05/17  00:16:44  ppessi
  13.  * Changed RCS version. Added rcsid.
  14.  *
  15.  * Revision 1.5  1993/04/05  19:06:36  jraja
  16.  * Changed storage of the spl functions  return values to type spl_t.
  17.  * Added include for conf.h to every .c file.
  18.  *
  19.  * Revision 1.4  93/03/05  21:09:42  21:09:42  jraja (Jarno Tapio Rajahalme)
  20.  * Fixed includes (again).
  21.  * 
  22.  * Revision 1.3  93/03/05  03:20:20  03:20:20  ppessi (Pekka Pessi)
  23.  * Compiles with SASC. Initial test version.
  24.  * 
  25.  * Revision 1.2  93/02/26  09:53:23  09:53:23  jraja (Jarno Tapio Rajahalme)
  26.  * Made this compile with ANSI C (added prototypes).
  27.  * Added second argument to tcp_quench to be able to use it as notify function
  28.  * with in_pcbnotify().
  29.  * 
  30.  * Revision 1.1  92/11/17  16:30:49  16:30:49  jraja (Jarno Tapio Rajahalme)
  31.  * Initial revision
  32.  *
  33.  */
  34.  
  35. /*
  36.  * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
  37.  * All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms, with or without
  40.  * modification, are permitted provided that the following conditions
  41.  * are met:
  42.  * 1. Redistributions of source code must retain the above copyright
  43.  *    notice, this list of conditions and the following disclaimer.
  44.  * 2. Redistributions in binary form must reproduce the above copyright
  45.  *    notice, this list of conditions and the following disclaimer in the
  46.  *    documentation and/or other materials provided with the distribution.
  47.  * 3. All advertising materials mentioning features or use of this software
  48.  *    must display the following acknowledgement:
  49.  *    This product includes software developed by the University of
  50.  *    California, Berkeley and its contributors.
  51.  * 4. Neither the name of the University nor the names of its contributors
  52.  *    may be used to endorse or promote products derived from this software
  53.  *    without specific prior written permission.
  54.  *
  55.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65.  * SUCH DAMAGE.
  66.  *
  67.  *    @(#)tcp_subr.c    7.20 (Berkeley) 12/1/90
  68.  */
  69.  
  70. #include <conf.h>
  71.  
  72. #include <sys/param.h>
  73. #include <sys/systm.h>
  74. #include <sys/malloc.h>
  75. #include <sys/mbuf.h>
  76. #include <sys/socket.h>
  77. #include <sys/socketvar.h>
  78. #include <sys/protosw.h>
  79. #include <sys/errno.h>
  80.  
  81. #include <net/route.h>
  82. #include <net/if.h>
  83.  
  84. #include <netinet/in.h>
  85. #include <netinet/in_systm.h>
  86. #include <netinet/ip.h>
  87. #include <netinet/in_pcb.h>
  88. #include <netinet/ip_var.h>
  89. #include <netinet/ip_icmp.h>
  90. #include <netinet/tcp.h>
  91. #include <netinet/tcp_fsm.h>
  92. #include <netinet/tcp_seq.h>
  93. #include <netinet/tcp_timer.h>
  94. #include <netinet/tcp_var.h>
  95. #include <netinet/tcpip.h>
  96.  
  97. #include <netinet/tcp_subr_protos.h>
  98. #include <netinet/tcp_output_protos.h>
  99. #include <netinet/ip_output_protos.h>
  100. #include <netinet/in_cksum_protos.h>
  101. #include <netinet/in_pcb_protos.h>
  102. #include <kern/uipc_socket2_protos.h>
  103. #include <kern/kern_synch_protos.h>
  104.  
  105. /* patchable/settable parameters for tcp */
  106. int    tcp_ttl = TCP_TTL;
  107. int     tcp_mssdflt = TCP_MSS;
  108. int     tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
  109.  
  110. extern    struct inpcb *tcp_last_inpcb;
  111.  
  112. /*
  113.  * Tcp initialization
  114.  */
  115. void
  116. tcp_init()
  117. {
  118.  
  119.     tcp_iss = 1;        /* wrong */
  120.     tcb.inp_next = tcb.inp_prev = &tcb;
  121.     if (max_protohdr < sizeof(struct tcpiphdr))
  122.         max_protohdr = sizeof(struct tcpiphdr);
  123.     if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
  124.         panic("tcp_init");
  125. }
  126.  
  127. /*
  128.  * Create template to be used to send tcp packets on a connection.
  129.  * Call after host entry created, allocates an mbuf and fills
  130.  * in a skeletal tcp/ip header, minimizing the amount of work
  131.  * necessary when the connection is used.
  132.  */
  133. struct tcpiphdr *
  134. tcp_template(tp)
  135.     struct tcpcb *tp;
  136. {
  137.     register struct inpcb *inp = tp->t_inpcb;
  138.     register struct mbuf *m;
  139.     register struct tcpiphdr *n;
  140.  
  141.     if ((n = tp->t_template) == 0) {
  142.         m = m_get(M_DONTWAIT, MT_HEADER);
  143.         if (m == NULL)
  144.             return (0);
  145.         m->m_len = sizeof (struct tcpiphdr);
  146.         n = mtod(m, struct tcpiphdr *);
  147.     }
  148.     n->ti_next = n->ti_prev = 0;
  149.     n->ti_x1 = 0;
  150.     n->ti_pr = IPPROTO_TCP;
  151.     n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
  152.     n->ti_src = inp->inp_laddr;
  153.     n->ti_dst = inp->inp_faddr;
  154.     n->ti_sport = inp->inp_lport;
  155.     n->ti_dport = inp->inp_fport;
  156.     n->ti_seq = 0;
  157.     n->ti_ack = 0;
  158.     n->ti_x2 = 0;
  159.     n->ti_off = 5;
  160.     n->ti_flags = 0;
  161.     n->ti_win = 0;
  162.     n->ti_sum = 0;
  163.     n->ti_urp = 0;
  164.     return (n);
  165. }
  166.  
  167. /*
  168.  * Send a single message to the TCP at address specified by
  169.  * the given TCP/IP header.  If m == 0, then we make a copy
  170.  * of the tcpiphdr at ti and send directly to the addressed host.
  171.  * This is used to force keep alive messages out using the TCP
  172.  * template for a connection tp->t_template.  If flags are given
  173.  * then we send a message back to the TCP which originated the
  174.  * segment ti, and discard the mbuf containing it and any other
  175.  * attached mbufs.
  176.  *
  177.  * In any case the ack and sequence number of the transmitted
  178.  * segment are as specified by the parameters.
  179.  */
  180. void
  181. tcp_respond(tp, ti, m, ack, seq, flags)
  182.     struct tcpcb *tp;
  183.     register struct tcpiphdr *ti;
  184.     register struct mbuf *m;
  185.     tcp_seq ack, seq;
  186.     int flags;
  187. {
  188.     register int tlen;
  189.     int win = 0;
  190.     struct route *ro = 0;
  191.  
  192.     if (tp) {
  193.         win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
  194.         ro = &tp->t_inpcb->inp_route;
  195.     }
  196.     if (m == 0) {
  197.         m = m_gethdr(M_DONTWAIT, MT_HEADER);
  198.         if (m == NULL)
  199.             return;
  200. #if TCP_COMPAT_42
  201.         tlen = 1;
  202. #else
  203.         tlen = 0;
  204. #endif
  205.         m->m_data += max_linkhdr;
  206.         *mtod(m, struct tcpiphdr *) = *ti;
  207.         ti = mtod(m, struct tcpiphdr *);
  208.         flags = TH_ACK;
  209.     } else {
  210.         m_freem(m->m_next);
  211.         m->m_next = 0;
  212.         m->m_data = (caddr_t)ti;
  213.         m->m_len = sizeof (struct tcpiphdr);
  214.         tlen = 0;
  215. #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
  216.         xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
  217.         xchg(ti->ti_dport, ti->ti_sport, u_short);
  218. #undef xchg
  219.     }
  220.     ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
  221.     tlen += sizeof (struct tcpiphdr);
  222.     m->m_len = tlen;
  223.     m->m_pkthdr.len = tlen;
  224.     m->m_pkthdr.rcvif = (struct ifnet *) 0;
  225.     ti->ti_next = ti->ti_prev = 0;
  226.     ti->ti_x1 = 0;
  227.     ti->ti_seq = htonl(seq);
  228.     ti->ti_ack = htonl(ack);
  229.     ti->ti_x2 = 0;
  230.     ti->ti_off = sizeof (struct tcphdr) >> 2;
  231.     ti->ti_flags = flags;
  232.     ti->ti_win = htons((u_short)win);
  233.     ti->ti_urp = 0;
  234.     ti->ti_sum = in_cksum(m, tlen);
  235.     ((struct ip *)ti)->ip_len = tlen;
  236.     ((struct ip *)ti)->ip_ttl = tcp_ttl;
  237.     (void) ip_output(m, (struct mbuf *)0, ro, 0);
  238. }
  239.  
  240. /*
  241.  * Create a new TCP control block, making an
  242.  * empty reassembly queue and hooking it to the argument
  243.  * protocol control block.
  244.  */
  245. struct tcpcb *
  246. tcp_newtcpcb(inp)
  247.     struct inpcb *inp;
  248. {
  249.     struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
  250.     register struct tcpcb *tp;
  251.  
  252.     if (m == NULL)
  253.         return ((struct tcpcb *)0);
  254.     tp = mtod(m, struct tcpcb *);
  255.     tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
  256.     tp->t_maxseg = tcp_mssdflt;
  257.  
  258.     tp->t_flags = 0;        /* sends options! */
  259.     tp->t_inpcb = inp;
  260.     /*
  261.      * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
  262.      * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
  263.      * reasonable initial retransmit time.
  264.      */
  265.     tp->t_srtt = TCPTV_SRTTBASE;
  266.     tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
  267.     tp->t_rttmin = TCPTV_MIN;
  268.     TCPT_RANGESET(tp->t_rxtcur, 
  269.         ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
  270.         TCPTV_MIN, TCPTV_REXMTMAX);
  271.     tp->snd_cwnd = TCP_MAXWIN;
  272.     tp->snd_ssthresh = TCP_MAXWIN;
  273.     inp->inp_ip.ip_ttl = tcp_ttl;
  274.     inp->inp_ppcb = (caddr_t)tp;
  275.     return (tp);
  276. }
  277.  
  278. /*
  279.  * Drop a TCP connection, reporting
  280.  * the specified error.  If connection is synchronized,
  281.  * then send a RST to peer.
  282.  */
  283. struct tcpcb *
  284. tcp_drop(tp, errno)
  285.     register struct tcpcb *tp;
  286.     int errno;
  287. {
  288.     struct socket *so = tp->t_inpcb->inp_socket;
  289.  
  290.     if (TCPS_HAVERCVDSYN(tp->t_state)) {
  291.         tp->t_state = TCPS_CLOSED;
  292.         (void) tcp_output(tp);
  293.         tcpstat.tcps_drops++;
  294.     } else
  295.         tcpstat.tcps_conndrops++;
  296.     if (errno == ETIMEDOUT && tp->t_softerror)
  297.         errno = tp->t_softerror;
  298.     so->so_error = errno;
  299.     return (tcp_close(tp));
  300. }
  301.  
  302. /*
  303.  * Close a TCP control block:
  304.  *    discard all space held by the tcp
  305.  *    discard internet protocol block
  306.  *    wake up any sleepers
  307.  */
  308. struct tcpcb *
  309. tcp_close(tp)
  310.     register struct tcpcb *tp;
  311. {
  312.     register struct tcpiphdr *t;
  313.     struct inpcb *inp = tp->t_inpcb;
  314.     struct socket *so = inp->inp_socket;
  315.     register struct mbuf *m;
  316. #ifdef RTV_RTT
  317.     register struct rtentry *rt;
  318.  
  319.     /*
  320.      * If we sent enough data to get some meaningful characteristics,
  321.      * save them in the routing entry.  'Enough' is arbitrarily 
  322.      * defined as the sendpipesize (default 4K) * 16.  This would
  323.      * give us 16 rtt samples assuming we only get one sample per
  324.      * window (the usual case on a long haul net).  16 samples is
  325.      * enough for the srtt filter to converge to within 5% of the correct
  326.      * value; fewer samples and we could save a very bogus rtt.
  327.      *
  328.      * Don't update the default route's characteristics and don't
  329.      * update anything that the user "locked".
  330.      */
  331.     if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
  332.         (rt = inp->inp_route.ro_rt) &&
  333.         ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
  334.         register u_long i;
  335.  
  336.         if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
  337.             i = tp->t_srtt *
  338.                 (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
  339.             if (rt->rt_rmx.rmx_rtt && i)
  340.                 /*
  341.                  * filter this update to half the old & half
  342.                  * the new values, converting scale.
  343.                  * See route.h and tcp_var.h for a
  344.                  * description of the scaling constants.
  345.                  */
  346.                 rt->rt_rmx.rmx_rtt =
  347.                     (rt->rt_rmx.rmx_rtt + i) / 2;
  348.             else
  349.                 rt->rt_rmx.rmx_rtt = i;
  350.         }
  351.         if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
  352.             i = tp->t_rttvar *
  353.                 (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
  354.             if (rt->rt_rmx.rmx_rttvar && i)
  355.                 rt->rt_rmx.rmx_rttvar =
  356.                     (rt->rt_rmx.rmx_rttvar + i) / 2;
  357.             else
  358.                 rt->rt_rmx.rmx_rttvar = i;
  359.         }
  360.         /*
  361.          * update the pipelimit (ssthresh) if it has been updated
  362.          * already or if a pipesize was specified & the threshhold
  363.          * got below half the pipesize.  I.e., wait for bad news
  364.          * before we start updating, then update on both good
  365.          * and bad news.
  366.          */
  367.         if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
  368.             (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh) ||
  369.             i < (rt->rt_rmx.rmx_sendpipe / 2)) {
  370.             /*
  371.              * convert the limit from user data bytes to
  372.              * packets then to packet data bytes.
  373.              */
  374.             i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
  375.             if (i < 2)
  376.                 i = 2;
  377.             i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr));
  378.             if (rt->rt_rmx.rmx_ssthresh)
  379.                 rt->rt_rmx.rmx_ssthresh =
  380.                     (rt->rt_rmx.rmx_ssthresh + i) / 2;
  381.             else
  382.                 rt->rt_rmx.rmx_ssthresh = i;
  383.         }
  384.     }
  385. #endif /* RTV_RTT */
  386.     /* free the reassembly queue, if any */
  387.     t = tp->seg_next;
  388.     while (t != (struct tcpiphdr *)tp) {
  389.         t = (struct tcpiphdr *)t->ti_next;
  390.         m = REASS_MBUF((struct tcpiphdr *)t->ti_prev);
  391.         remque(t->ti_prev);
  392.         m_freem(m);
  393.     }
  394.     if (tp->t_template)
  395.         (void) m_free(dtom(tp->t_template));
  396.     (void) m_free(dtom(tp));
  397.     inp->inp_ppcb = 0;
  398.     soisdisconnected(so);
  399.     /* clobber input pcb cache if we're closing the cached connection */
  400.     if (inp == tcp_last_inpcb)
  401.         tcp_last_inpcb = &tcb;
  402.     in_pcbdetach(inp);
  403.     tcpstat.tcps_closed++;
  404.     return ((struct tcpcb *)0);
  405. }
  406.  
  407. void
  408. tcp_drain()
  409. {
  410.  
  411. }
  412.  
  413. /*
  414.  * Notify a tcp user of an asynchronous error;
  415.  * store error as soft error, but wake up user
  416.  * (for now, won't do anything until can select for soft error).
  417.  */
  418. void
  419. tcp_notify(inp, error)
  420.     register struct inpcb *inp;
  421.     int error;
  422. {
  423.  
  424.     ((struct tcpcb *)inp->inp_ppcb)->t_softerror = error;
  425.     wakeup((caddr_t) &inp->inp_socket->so_timeo);
  426.     sorwakeup(inp->inp_socket);
  427.     sowwakeup(inp->inp_socket);
  428. }
  429.  
  430. void
  431. tcp_ctlinput(cmd, sa, ip)
  432.     int cmd;
  433.     struct sockaddr *sa;
  434.     register struct ip *ip;
  435. {
  436.     register struct tcphdr *th;
  437.     extern struct in_addr zeroin_addr;
  438.     extern u_char inetctlerrmap[];
  439.     void (*notify)(register struct inpcb * inp, int error) = tcp_notify;
  440.  
  441.     if (cmd == PRC_QUENCH)
  442.         notify = tcp_quench;
  443.     else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
  444.         return;
  445.     if (ip) {
  446.         th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
  447.         in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
  448.             cmd, notify);
  449.     } else
  450.         in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
  451. }
  452.  
  453. /*
  454.  * When a source quench is received, close congestion window
  455.  * to one segment.  We will gradually open it again as we proceed.
  456.  */
  457. void
  458. tcp_quench(inp, error)
  459.      struct inpcb *inp;
  460.      int error;
  461. {
  462.     struct tcpcb *tp = intotcpcb(inp);
  463.  
  464.     if (tp)
  465.         tp->snd_cwnd = tp->t_maxseg;
  466. }
  467.  
  468.  
  469.